/* ****************************************************************
   ****************************************************************
   * Com++ Professional (c) 2009 C++ World
   * http://www.cplusplusworld.com/ mailto:compp@cplusplusworld.com
   ****************************************************************
   ****************************************************************
*/

#ifndef  SOCKET_H
#define  SOCKET_H

#include "SysPlusPlus/GenCfg.h"

#include <iostream>
#include <cstring>
#include <string>
#include <unistd.h>
#include <fcntl.h>
#include <sys/un.h>

//#include "config.h"
#include "ComPlusPlus/Comm.h"

#ifndef INADDR_NONE
# define INADDR_NONE (in_addr_t) -1
#endif


namespace compp {

  enum SockStates { Idle, Bound, Listening, Connected, Accepted }  ;


  enum IPADDRVERS { IPADDRV4, IPADDRV6 }  ;

  const std::string SocketANYHOST = "0.0.0.0";

  /**
   * Socket  Class. Handling of all protcol independent processing.
   */
class Socket : public Comm {

 protected:
  
    int               Address             ;         // The Address
    enum SockStates   State               ;         // Idle || Bound || Listening || Connected || Accepted

    // Options 

    bool              UseDns          ;  
    int               LingerSeconds   ;
    int               MaxNumBytes     ;  

    bool _Connect( const std::string &addr, const int port );

    std::string ContextString;

  // Socket Options

    std::string  SocketAddress ;
    int SocketPort;
  

 public:

    void SetLingerTime ( int secs ) ;
    int GetLingerTime ( ) const ;
    bool GetUseDNS () const ;
    void SetUseDNS (bool val) ;

    const std::string  GetSocketAddress() const ;
    const int GetSocketPort() const ;

    void _MkSockaddrIPV4( const std::string &addr, const int port, struct sockaddr_in *ad );
    void _MkIPAddrIPV4( const std::string &addr, struct in_addr *ad ) ;
    

    // Destructor
    virtual ~Socket () ;

    // Constructor
    Socket ( ) ;
    Socket ( unsigned int buffsz  ) ;

    bool SetSockOptReuseAddress ( bool yesno );
    bool SetSockOptLinger ( int secs ) ;
    bool SetSockOptKeepAlive ( bool yesno );
    bool SetSockOptOobinline( bool yes ) ;
    bool SetSockOptDontroute (bool yes ) ;
    bool SetSockOptSndBuf ( int bytes ) ;
    bool SetSockOptRcvBuf ( int bytes) ;
    bool SetSockOptPriority( bool yes) ;
    
    int Send ( const void *buf, size_t len, int flags);
    int Send ( const void *buf, size_t len);

    int Recv(void *buf, int len, int flags=0);

    void SetContextString ( std::string & s ) ;
    std::string GetContextString (  ) ;

protected:

    int Recvfrom(void *buf, int len, int flags, struct sockaddr *from, int *fromlen);
    
  } ;
}

#endif


